<template>
  <div class="chat-page">
    <div class="chat-wrap card-neo">
    <header class="topbar">
      <button class="back" @click="$router.push('/')">← 返回</button>
      <div class="title">AI 宠物专家</div>
      <div class="chat-id">ID: {{ chatId }}</div>
    </header>

    <div class="messages" ref="messagesRef">
      <div v-for="(m, idx) in messages" :key="idx" class="msg" :class="m.role">
        <img class="avatar" :src="m.role === 'ai' ? aiAvatar : userAvatar" alt="" />
        <div class="bubble">{{ m.content }}</div>
      </div>
    </div>

    <footer class="composer">
      <input v-model="input" @keydown.enter="send" placeholder="输入你的问题..." />
      <button :disabled="pending || !input.trim()" @click="send">发送</button>
    </footer>
    </div>
  </div>
</template>

<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, reactive, ref, watchEffect } from 'vue'
import { v4 as uuidv4 } from 'uuid'
import { createEventSourceSSE } from '../utils/sse'
// 内置默认头像（SVG Data URI），避免外网加载失败
const aiAvatar = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="%237c3aed"/><stop offset="100%" stop-color="%2322d3ee"/></linearGradient></defs><circle cx="32" cy="32" r="32" fill="url(%23g)"/><circle cx="32" cy="26" r="12" fill="white" opacity="0.9"/><rect x="14" y="40" width="36" height="14" rx="7" fill="white" opacity="0.9"/></svg>'
const userAvatar = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><circle cx="32" cy="32" r="32" fill="%231677ff"/><circle cx="32" cy="26" r="12" fill="white" opacity="0.9"/><rect x="14" y="40" width="36" height="14" rx="7" fill="white" opacity="0.9"/></svg>'

type ChatMessage = { role: 'user' | 'ai', content: string }

const messages = reactive<ChatMessage[]>([])
const input = ref('')
const messagesRef = ref<HTMLDivElement | null>(null)
const pending = ref(false)
const chatId = ref('')
let currentEs: EventSource | null = null

onMounted(() => {
  chatId.value = uuidv4()
})

onUnmounted(() => {
  if (currentEs) currentEs.close()
})

// 内容变化也触发滚动（不仅仅是数组长度变化）
watchEffect(() => {
  // 将所有内容连接用于依赖追踪
  const _ = messages.map(m => m.content).join('|')
  void _
  requestAnimationFrame(() => {
    const el = messagesRef.value
    if (el) el.scrollTop = el.scrollHeight
  })
})

function send() {
  const text = input.value.trim()
  if (!text || pending.value) return

  messages.push({ role: 'user', content: text })
  input.value = ''

  // AI 占位消息（必须是 reactive，避免直接修改原始对象导致视图不更新）
  const aiMsg = reactive<ChatMessage>({ role: 'ai', content: '' })
  messages.push(aiMsg)

  pending.value = true
  const url = new URL('http://localhost:9080/api/cat-agent/normal/chat')
  url.searchParams.set('message', text)
  url.searchParams.set('chatId', chatId.value)

  // 逐字即时渲染：每个 SSE message 到达就立刻追加到同一气泡

  const es = createEventSourceSSE(url.toString(), (chunk) => {
    if (chunk) aiMsg.content += chunk
  }, () => {
    pending.value = false
  })
  if (currentEs) currentEs.close()
  currentEs = es

  // no-op
}
</script>

<style scoped>
.chat-page { padding: 24px 12px; }
.chat-wrap { max-width: 980px; height: calc(100vh - 72px); margin: 0 auto; display: grid; grid-template-rows: 56px 1fr 72px; overflow: hidden; }
.topbar {
  display: grid;
  grid-template-columns: 80px 1fr auto;
  align-items: center;
  padding: 0 12px;
  border-bottom: 1px solid var(--border, #eee);
}
.back { border: none; background: transparent; cursor: pointer; font-size: 16px; }
.title { font-weight: 600; text-align: center; }
.chat-id { font-size: 12px; color: #999; }

.messages {
  padding: 16px 16px 0 16px;
  overflow: auto;
  background: transparent;
}
.msg { display: flex; margin-bottom: 12px; align-items: flex-start; gap: 8px; }
.msg.user { justify-content: flex-end; }
.msg.ai { justify-content: flex-start; }
.msg.user { flex-direction: row-reverse; }
.avatar{ width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--border, #eee); }
.bubble {
  max-width: 72ch;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(255,255,255,.9);
  border: 1px solid var(--border, #eee);
  text-align: left;
  color: #111;
}
.msg.user .bubble { background: #1677ff; color: #fff; border-color: #1677ff; }

.composer {
  display: grid;
  grid-template-columns: 1fr 100px;
  gap: 8px;
  padding: 8px 12px;
  border-top: 1px solid var(--border, #eee);
}
.composer input {
  height: 44px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1px solid var(--border, #ddd);
}
.composer button {
  height: 44px;
  border-radius: 10px;
  border: none;
  background: #1677ff;
  color: #fff;
  cursor: pointer;
}
.composer button:disabled { opacity: .6; cursor: not-allowed; }
</style>



